package luke.ui.components;

import javax.swing.*;
import javax.swing.event.DocumentListener; // 添加DocumentListener导入
import java.awt.*;
import java.io.File;
import java.util.Collections;
import java.util.Set;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.LinkedHashSet;
import java.awt.Font; // 添加Font类的导入

import luke.core.controller.PlayController;

import java.util.prefs.Preferences;

import luke.audio.metadata.Song;

// 导入PlaybackStateManager
import luke.core.utils.PlaybackStateManager;
import luke.core.config.FavoritesManager;  // 新增：导入FavoritesManager
import luke.core.utils.SvgIconLoader;  // 新增：导入SvgIconLoader
import luke.core.utils.AppStateManager;  // 新增：导入AppStateManager
import luke.core.logging.LogUtil; // 添加LogUtil导入
import luke.core.utils.LanguageManager; // 新增：导入LanguageManager

import java.awt.event.MouseAdapter;  // 新增：导入MouseAdapter
import java.awt.event.MouseEvent;  // 新增：导入MouseEvent
import java.awt.datatransfer.StringSelection; // 新增：导入StringSelection
import java.awt.dnd.DnDConstants; // 新增：导入DnDConstants
import java.awt.dnd.DragGestureEvent; // 新增：导入DragGestureEvent
import java.awt.dnd.DragGestureListener; // 新增：导入DragGestureListener
import java.awt.dnd.DragSource; // 新增：导入DragSource
import java.awt.dnd.DropTarget; // 新增：导入DropTarget
import java.awt.dnd.DropTargetDragEvent; // 新增：导入DropTargetDragEvent
import java.awt.dnd.DropTargetDropEvent; // 新增：导入DropTargetDropEvent
import java.awt.dnd.DropTargetEvent; // 新增：导入DropTargetEvent
import java.awt.dnd.DropTargetListener; // 新增：导入DropTargetListener


public class SelectedFilePanel extends JPanel {
    private final PlayController playController;
    private JList<String> selectedFilesList;
    private DefaultListModel<String> selectedFilesListModel;
    private JLabel selectedCountLabel;
    private List<File> sharedSelectedFiles;

    private Map<File, Song> songData; // 歌曲数据缓存
    private JTextField durationField; // 时长输入框
    private JCheckBox truncateExceedingFilesCheckBox; // 截断超出文件勾选框

    // 添加PlaybackStateManager引用
    private PlaybackStateManager playbackStateManager;

    // 添加AppStateManager引用
    private AppStateManager appStateManager;

    // 添加FavoritesManager引用
    private FavoritesManager favoritesManager;  // 新增：收藏管理器

    // 添加收藏相关的组件
    private JLabel favoritesButton;  // 收藏图标按钮
    private JLabel addFavoriteButton;  // 加入收藏图标按钮
    private JPopupMenu favoritesPopup;  // 收藏弹出菜单
    private JList<String> favoritesList;  // 收藏列表
    private DefaultListModel<String> favoritesListModel;  // 收藏列表模型
    private List<File> allListFiles;  // 所有文件列表

    // 持久化配置
    private Preferences prefs = Preferences.userNodeForPackage(SelectedFilePanel.class);
    
    // 添加LanguageManager引用
    private LanguageManager languageManager;



    public SelectedFilePanel() {
        // 初始化LanguageManager
        this.languageManager = LanguageManager.getInstance();
        
        // 初始化PlaybackStateManager并注册为监听器
        this.playbackStateManager = PlaybackStateManager.getInstance();
        this.appStateManager = AppStateManager.getInstance();
        this.sharedSelectedFiles = appStateManager.getSharedSelectedFiles();
        this.songData = appStateManager.getSongData();
        this.allListFiles = appStateManager.getAllListFiles();
        this.playbackStateManager.addListener(new PlaybackStateManager.MetadataListener() {
            @Override
            public void onBpmChanged(double bpm) {
                File currentFile = playbackStateManager.getCurrentFile();
                //刷新bpm显示
                updateFileBPMDisplay(currentFile);
            }
        });
        playController = PlayController.getInstance();
        this.appStateManager.addListener(new AppStateManager.StateListener() {
            @Override
            public void onSelectedFilesChanged() {
                updateSelectedFiles();
            }

            @Override
            public void onBpmFileAcquired(File bpmFileAcquired) {
                updateFileBPMDisplay(bpmFileAcquired);
            }
        });

        // 初始化AppStateManager并注册为监听器

        this.durationField = null;
        this.truncateExceedingFilesCheckBox = null; // 初始化截断超出文件勾选框
        this.favoritesManager = new FavoritesManager();  // 新增：初始化收藏管理器


        setLayout(new GridBagLayout());
        setBorder(BorderFactory.createTitledBorder(languageManager.getPanelText("selected.files.title")));
        // 设置固定的最小和最大尺寸，避免UI跳动
        setMinimumSize(new Dimension(300, 200));
        setPreferredSize(new Dimension(350, 600));
        setMaximumSize(new Dimension(500, Short.MAX_VALUE));

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.weightx = 1;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.insets = new Insets(5, 5, 5, 5);


        // 初始化已选择文件列表模型和列表
        initSelectedFilesList();

        // 添加控制按钮面板（在滚动面板上方）
        JPanel controlButtonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5));
        controlButtonPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 30));

        JButton clearSelectionButton = new JButton(languageManager.getPanelText("selected.files.clear"));
        clearSelectionButton.putClientProperty("JButton.buttonType", "roundRect");
        clearSelectionButton.addActionListener(e -> clearSelectedFiles());

        JButton smartSelectButton = new JButton(languageManager.getPanelText("selected.files.smart.select"));
        smartSelectButton.putClientProperty("JButton.buttonType", "roundRect");

        JButton smartAppendButton = new JButton(languageManager.getPanelText("selected.files.smart.append"));
        smartAppendButton.putClientProperty("JButton.buttonType", "roundRect");

        // 修改：使用图标标签替换按钮
        favoritesButton = new JLabel();
        favoritesButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
        favoritesButton.setToolTipText(languageManager.getPanelText("selected.files.favorites"));
        // 设置收藏图标，使用统一的正方形尺寸以避免压扁
        SvgIconLoader.setButtonIcon(favoritesButton, "ico/收藏.svg", 16, 16);

        addFavoriteButton = new JLabel();
        addFavoriteButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
        addFavoriteButton.setToolTipText(languageManager.getPanelText("selected.files.add.to.favorites"));
        // 设置加入收藏图标，使用统一的正方形尺寸
        SvgIconLoader.setButtonIcon(addFavoriteButton, "ico/加入收藏.svg", 16, 16);

        // 初始化收藏弹出菜单
        initFavoritesPopup();

        // 添加事件监听器
        setupEventListeners();

        // 添加时长输入面板
        JPanel durationPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5));
        durationPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 40));
        durationPanel.add(new JLabel(languageManager.getPanelText("selected.files.duration.label")));
        durationField = new JTextField(8);
        // 加载持久化的时长值
        int persistedDuration = prefs.getInt("duration", 90);
        durationField.setText(String.valueOf(persistedDuration));
        // 同时更新AppStateManager中的计划生成时长
        if (appStateManager != null) {
            appStateManager.setPlannedDuration(persistedDuration);
        }
        // 为时长输入框添加工具提示
        durationField.setToolTipText(languageManager.getPanelText("selected.files.duration.label"));
        durationField.setInputVerifier(new InputVerifier() {
            @Override
            public boolean verify(JComponent input) {
                JTextField field = (JTextField) input;
                try {
                    double value = Double.parseDouble(field.getText());
                    if (value <= 0 || value > 360) {
                        // 获取主窗口作为父组件，使对话框在屏幕中央显示
                        Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
                        JOptionPane.showMessageDialog(parentFrame,
                                languageManager.getPanelText("panel.production.video.default.title.no.bpm"), 
                                languageManager.getString("panel.common.warning.title"),
                                JOptionPane.WARNING_MESSAGE);
                        return false;
                    }
                    // 验证成功时调用自定义方法
                    onDurationValidated(value);
                    return true;
                } catch (NumberFormatException e) {
                    // 获取主窗口作为父组件，使对话框在屏幕中央显示
                    Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
                    JOptionPane.showMessageDialog(parentFrame,
                            languageManager.getString("dialog.donation.qr.error"), 
                            languageManager.getString("panel.common.warning.title"),
                            JOptionPane.WARNING_MESSAGE);
                    return false;
                }
            }
        });
        
        // 添加文档监听器，实时保存时长值的更改
        durationField.getDocument().addDocumentListener(new javax.swing.event.DocumentListener() {
            @Override
            public void insertUpdate(javax.swing.event.DocumentEvent e) {
                saveDuration();
            }

            @Override
            public void removeUpdate(javax.swing.event.DocumentEvent e) {
                saveDuration();
            }

            @Override
            public void changedUpdate(javax.swing.event.DocumentEvent e) {
                saveDuration();
            }

            private void saveDuration() {
                try {
                    double value = Double.parseDouble(durationField.getText());
                    if (value > 0 && value <= 360) {
                        prefs.putInt("duration", (int) value);
                        // 同时更新AppStateManager中的计划生成时长
                        if (appStateManager != null) {
                            appStateManager.setPlannedDuration(value);
                        }
                    }
                } catch (NumberFormatException e) {
                    // 忽略无效的数字格式
                }
            }
        });
        
        durationPanel.add(durationField);

        // 添加截断超出文件勾选框
        truncateExceedingFilesCheckBox = new JCheckBox(languageManager.getPanelText("selected.files.truncate"));
        truncateExceedingFilesCheckBox.setToolTipText(languageManager.getPanelText("selected.files.truncate"));
        // 加载持久化的勾选状态，默认不勾选
        boolean persistedTruncateExceeding = prefs.getBoolean("truncateExceedingFiles", false);
        LogUtil.debug("SelectedFilePanel", "initComponents", "从持久化存储中恢复截断选项状态: " + persistedTruncateExceeding);
        truncateExceedingFilesCheckBox.setSelected(persistedTruncateExceeding);
        durationPanel.add(truncateExceedingFilesCheckBox);

        // 为勾选框添加监听器，持久化设置
        truncateExceedingFilesCheckBox.addActionListener(e -> {
            boolean selected = truncateExceedingFilesCheckBox.isSelected();
            prefs.putBoolean("truncateExceedingFiles", selected);
            LogUtil.debug("SelectedFilePanel", "truncateExceedingFilesCheckBox.addActionListener", "截断选项状态已更改: " + selected);
            // 同时更新AppStateManager中的设置
            if (appStateManager != null) {
                appStateManager.setTruncateExceedingFiles(selected);
                LogUtil.debug("SelectedFilePanel", "truncateExceedingFilesCheckBox.addActionListener", "已更新AppStateManager中的截断选项状态: " + appStateManager.isTruncateExceedingFiles());
            }
        });
        
        // 确保AppStateMananger中的初始状态与UI同步
        if (appStateManager != null) {
            appStateManager.setTruncateExceedingFiles(persistedTruncateExceeding);
            LogUtil.debug("SelectedFilePanel", "initComponents", "初始化时同步AppStateMananger中的截断选项状态: " + appStateManager.isTruncateExceedingFiles());
        }


        controlButtonPanel.add(clearSelectionButton);
        controlButtonPanel.add(smartSelectButton);
        controlButtonPanel.add(smartAppendButton);
        // 修改：将收藏相关图标放在最右边
        controlButtonPanel.add(Box.createHorizontalGlue()); // 添加弹性空间
        controlButtonPanel.add(favoritesButton);
        controlButtonPanel.add(addFavoriteButton);

        // 添加按钮事件监听器
        smartSelectButton.addActionListener(e -> smartSelect());
        smartAppendButton.addActionListener(e -> smartAppend());

        // 重新设计布局：按照固定高度比例分配，避免列表内容变化时UI跳动
        // 容器A：控制按钮面板（固定高度，减少高度）
        gbc.gridy = 0;
        gbc.weighty = 0; // 不分配权重，使用固定高度
        gbc.ipady = 1; // 减少内部填充高度
        add(controlButtonPanel, gbc);

        // 容器B：时长输入面板（固定高度，减少高度）
        gbc.gridy = 1;
        gbc.weighty = 0;
        gbc.ipady = 1; // 减少内部填充高度
        add(durationPanel, gbc);

        // 容器C：滚动列表面板（使用权重分配剩余空间，增加高度占比）
        JScrollPane scrollPane = new JScrollPane(selectedFilesList);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        scrollPane.setBorder(BorderFactory.createEmptyBorder());

        gbc.gridy = 2;
        gbc.weighty = 9; // 增加滚动区域的高度权重
        gbc.ipady = 0; // 重置内部填充
        add(scrollPane, gbc);

        // 已选择文件数量标签放在底部（固定高度）
        selectedCountLabel = new JLabel(languageManager.getPanelText("selected.files.count", sharedSelectedFiles.size()));
        selectedCountLabel.setHorizontalAlignment(SwingConstants.LEFT);

        // 创建一个面板来放置已选择文件数量标签和收藏图标
        JPanel bottomPanel = new JPanel(new BorderLayout());
        bottomPanel.add(selectedCountLabel, BorderLayout.WEST);

        // 创建一个放置收藏图标的面板
        JPanel favoritesPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0));
        favoritesPanel.add(favoritesButton);
        favoritesPanel.add(addFavoriteButton);
        bottomPanel.add(favoritesPanel, BorderLayout.EAST);

        gbc.gridy = 3;
        gbc.weighty = 0;
        gbc.ipady = 1;
        add(bottomPanel, gbc);
    }

    /**
     * 初始化已选择文件列表模型和列表
     */
    private void initSelectedFilesList() {
        selectedFilesListModel = new DefaultListModel<>();
        selectedFilesList = new JList<>(selectedFilesListModel);
        selectedFilesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        // 启用拖拽功能
        enableDragAndDrop();

        // 为已选择列表添加工具提示
        selectedFilesList.setToolTipText(languageManager.getPanelText("file.list.play.tooltip"));

        // 移除固定宽度设置，使用自适应宽度
        // selectedFilesList.setFixedCellWidth(300);

        // 设置自定义渲染器 - 文件名左对齐，BPM右对齐
        selectedFilesList.setCellRenderer(new ListCellRenderer() {
            @Override
            public Component getListCellRendererComponent(JList list, Object value, int index,
                                                          boolean isSelected, boolean cellHasFocus) {
                // 创建主面板，使用BorderLayout布局
                JPanel panel = new JPanel(new BorderLayout());
                panel.setOpaque(true);

                // 获取原始文件名（去除HTML标签）
                String text = value.toString();
                String fileName = text;
                String bpmInfo = "";

                // 如果是HTML格式，提取文件名和BPM信息
                if (text.startsWith("<html>")) {
                    // 简化的HTML解析，提取文件名和BPM
                    int nameLabelStart = text.indexOf("<td width='220' align='left'><nobr>") + 34;
                    int nameLabelEnd = text.indexOf("</nobr></td>", nameLabelStart);
                    if (nameLabelStart > 33 && nameLabelEnd > nameLabelStart) {
                        fileName = text.substring(nameLabelStart, nameLabelEnd);
                    }

                    int bpmLabelStart = text.indexOf("<td width='80' align='right'><nobr>") + 34;
                    int bpmLabelEnd = text.indexOf("</nobr></td>", bpmLabelStart);
                    if (bpmLabelStart > 33 && bpmLabelEnd > bpmLabelStart) {
                        bpmInfo = text.substring(bpmLabelStart, bpmLabelEnd);
                    }
                }

                // 去掉可能存在的>符号
                if (fileName.startsWith(">")) {
                    fileName = fileName.substring(1);
                }
                if (fileName.endsWith(">")) {
                    fileName = fileName.substring(0, fileName.length() - 1);
                }
                if (bpmInfo.startsWith(">")) {
                    bpmInfo = bpmInfo.substring(1);
                }
                if (bpmInfo.endsWith(">")) {
                    bpmInfo = bpmInfo.substring(0, bpmInfo.length() - 1);
                }

                // 创建文件名标签（左对齐）
                JLabel nameLabel = new JLabel(fileName);
                nameLabel.setHorizontalAlignment(SwingConstants.LEFT);
                nameLabel.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5));
                // 设置最大宽度以防止过长文件名影响布局
                nameLabel.setMaximumSize(new Dimension(200, Integer.MAX_VALUE));

                // 创建BPM标签（右对齐）
                JLabel bpmLabel = new JLabel(bpmInfo);
                bpmLabel.setHorizontalAlignment(SwingConstants.RIGHT);
                bpmLabel.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5));
                // 设置固定宽度以确保BPM信息对齐
                bpmLabel.setPreferredSize(new Dimension(80, bpmLabel.getPreferredSize().height));
                bpmLabel.setMinimumSize(new Dimension(80, bpmLabel.getPreferredSize().height));
                bpmLabel.setMaximumSize(new Dimension(80, bpmLabel.getPreferredSize().height));

                // 设置选中状态的背景和前景色
                if (isSelected) {
                    panel.setBackground(list.getSelectionBackground());
                    nameLabel.setForeground(list.getSelectionForeground());
                    bpmLabel.setForeground(list.getSelectionForeground());
                } else {
                    panel.setBackground(list.getBackground());
                    nameLabel.setForeground(new Color(220, 220, 220)); // 使用用户偏好的#1296db颜色
                    bpmLabel.setForeground(new Color(224, 98, 13)); // BPM使用绿色
                }

                // 添加拖拽指示器（仅在鼠标悬停时显示）
                JLabel dragIndicator = new JLabel("≡"); // 使用三横线符号作为拖拽指示器
                dragIndicator.setForeground(Color.GRAY);
                dragIndicator.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
                panel.add(dragIndicator, BorderLayout.WEST);

                // 将标签添加到面板中
                panel.add(nameLabel, BorderLayout.CENTER);
                panel.add(bpmLabel, BorderLayout.EAST);

                return panel;
            }
        });

        // 添加鼠标点击事件处理 - 点击文件时播放音乐
        selectedFilesList.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
            public void mouseClicked(java.awt.event.MouseEvent e) {
                if (e.getClickCount() == 1) { // 单击事件
                    int index = selectedFilesList.locationToIndex(e.getPoint());
                    if (index >= 0) {
                        // 获取对应的文件对象
                        java.util.List<File> fileList = new java.util.ArrayList<>(sharedSelectedFiles);
                        if (index < fileList.size()) {
                            File file = fileList.get(index);
                            playController.setInputCurrentFile(file);
                            playController.togglePlayback();

                            // 通过AppStateManager发送搜索文本状态变化，而不是直接调用回调
                            if (appStateManager != null) {
                                String fileName = file.getName();
                                // 移除文件扩展名
                                int dotIndex = fileName.lastIndexOf('.');
                                if (dotIndex > 0) {
                                    fileName = fileName.substring(0, dotIndex);
                                }
                                appStateManager.setSearchText(fileName);
                            }
                        }
                    }
                }
            }
        });
    }

    /**
     * 启用拖拽功能
     */
    private void enableDragAndDrop() {
        // 创建拖拽源
        DragSource dragSource = DragSource.getDefaultDragSource();
        dragSource.createDefaultDragGestureRecognizer(selectedFilesList,
                DnDConstants.ACTION_MOVE, new DragGestureListener() {
                    @Override
                    public void dragGestureRecognized(DragGestureEvent dge) {
                        int index = selectedFilesList.getSelectedIndex();
                        if (index != -1) {
                            StringSelection transferable = new StringSelection(String.valueOf(index));
                            // 添加拖拽开始时的视觉反馈
                            selectedFilesList.setCursor(DragSource.DefaultMoveDrop);
                            dge.startDrag(DragSource.DefaultMoveDrop, transferable);
                        }
                    }
                });

        // 创建放置目标
        selectedFilesList.setDropTarget(new DropTarget(selectedFilesList, new DropTargetListener() {
            // 自动滚动相关变量
            private Timer autoScrollTimer = null;
            private int scrollDirection = 0; // -1 向上滚动, 1 向下滚动, 0 不滚动
            private Point dragStartPoint = null; // 记录拖拽开始位置（相对于整个屏幕）
            private Point lastDragPoint = null; // 记录最后一次拖拽位置（相对于整个屏幕）

            @Override
            public void dragEnter(DropTargetDragEvent dtde) {
                // 接受所有拖拽操作
                dtde.acceptDrag(DnDConstants.ACTION_MOVE);
                // 初始化滚动方向
                scrollDirection = 0;
                // 记录拖拽开始位置（相对于整个屏幕）
                dragStartPoint = dtde.getLocation();
                // 转换为屏幕坐标
                Point screenPoint = new Point(dragStartPoint);
                SwingUtilities.convertPointToScreen(screenPoint, selectedFilesList);
                dragStartPoint = screenPoint;
                lastDragPoint = new Point(dragStartPoint);
            }

            @Override
            public void dragOver(DropTargetDragEvent dtde) {
                // 接受所有拖拽操作
                dtde.acceptDrag(DnDConstants.ACTION_MOVE);

                // 获取滚动面板
                JScrollPane scrollPane = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, selectedFilesList);
                if (scrollPane != null) {
                    JViewport viewport = scrollPane.getViewport();
                    Point viewPosition = viewport.getViewPosition();
                    int viewportHeight = viewport.getHeight();
                    int listHeight = selectedFilesList.getHeight();
                    Point point = dtde.getLocation();

                    // 转换为屏幕坐标
                    Point screenPoint = new Point(point);
                    SwingUtilities.convertPointToScreen(screenPoint, selectedFilesList);

                    // 更新最后拖拽位置
                    lastDragPoint = new Point(screenPoint);

                    // 检查是否需要自动滚动
                    scrollDirection = 0;

                    // 根据鼠标相对于开始位置的移动方向来决定滚动方向
                    // 只根据鼠标按下坐标来决定往上还是往下滚动，不使用边缘触发
                    if (dragStartPoint != null) {
                        // 增大阈值到50像素，使滚动触发更明显
                        // 如果鼠标在开始位置上方且可以向上滚动（显示上方内容）
                        if (screenPoint.y < dragStartPoint.y - 50 && viewPosition.y > 0) {
                            scrollDirection = -1; // 向上滚动
                        }
                        // 如果鼠标在开始位置下方且可以向下滚动（显示下方内容）
                        else if (screenPoint.y > dragStartPoint.y + 50 && viewPosition.y + viewportHeight < listHeight) {
                            scrollDirection = 1; // 向下滚动
                        }
                    }

                    // 启动或停止自动滚动
                    if (scrollDirection != 0) {
                        if (autoScrollTimer == null) {
                            startAutoScrollTimer(scrollPane, viewport, screenPoint);
                        }
                    } else {
                        stopAutoScrollTimer();
                    }
                }
            }

            @Override
            public void dropActionChanged(DropTargetDragEvent dtde) {
                // 不需要特殊处理
            }

            @Override
            public void dragExit(DropTargetEvent dte) {
                // 恢复光标并停止自动滚动
                selectedFilesList.setCursor(Cursor.getDefaultCursor());
                stopAutoScrollTimer();
                // 清除拖拽位置信息
                dragStartPoint = null;
                lastDragPoint = null;
            }

            @Override
            public void drop(DropTargetDropEvent dtde) {
                try {
                    // 停止自动滚动并恢复光标
                    stopAutoScrollTimer();
                    selectedFilesList.setCursor(Cursor.getDefaultCursor());

                    // 获取拖拽点位置
                    Point point = dtde.getLocation();
                    int dropIndex = selectedFilesList.locationToIndex(point);

                    if (dropIndex != -1) {
                        // 获取当前选中的索引
                        int selectedIndex = selectedFilesList.getSelectedIndex();

                        if (selectedIndex != -1 && selectedIndex != dropIndex) {
                            // 接受拖拽操作
                            dtde.acceptDrop(DnDConstants.ACTION_MOVE);

                            // 计算实际插入位置
                            Rectangle cellBounds = selectedFilesList.getCellBounds(dropIndex, dropIndex);
                            if (cellBounds != null && point.y > cellBounds.y + cellBounds.height / 2) {
                                dropIndex++; // 插入到下一个位置
                            }

                            // 确保插入位置在有效范围内
                            dropIndex = Math.min(dropIndex, sharedSelectedFiles.size());

                            // 重新排列文件列表
                            if (selectedIndex != dropIndex) {
                                // 从原位置移除
                                File movedFile = sharedSelectedFiles.remove(selectedIndex);
                                // 插入到新位置
                                sharedSelectedFiles.add(dropIndex, movedFile);

                                // 手动更新列表模型，保持顺序一致
                                updateListModelAfterDrag(selectedIndex, dropIndex);

                                // 更新选中索引
                                selectedFilesList.setSelectedIndex(dropIndex);

                                // 通知已选择列表发生变化
                                if (appStateManager != null) {
                                    notifySelectionChanged();
                                }

                                // 通知选择变化
                                notifySelectionChanged();
                            }

                            // 完成拖拽操作
                            dtde.dropComplete(true);
                            // 清除拖拽位置信息
                            dragStartPoint = null;
                            lastDragPoint = null;
                            return;
                        }
                    }

                    // 拒绝拖拽操作
                    dtde.rejectDrop();
                    // 清除拖拽位置信息
                    dragStartPoint = null;
                    lastDragPoint = null;
                } catch (Exception e) {
                    e.printStackTrace();
                    // 恢复光标并停止自动滚动
                    selectedFilesList.setCursor(Cursor.getDefaultCursor());
                    stopAutoScrollTimer();
                    dtde.rejectDrop();
                    // 清除拖拽位置信息
                    dragStartPoint = null;
                    lastDragPoint = null;
                }
            }

            /**
             * 启动自动滚动定时器
             */
            private void startAutoScrollTimer(JScrollPane scrollPane, JViewport viewport, Point currentPoint) {
                if (autoScrollTimer != null) {
                    autoScrollTimer.stop();
                }

                autoScrollTimer = new Timer(100, e -> {
                    Point viewPosition = viewport.getViewPosition();
                    int maxScroll = selectedFilesList.getHeight() - viewport.getHeight();

                    // 根据距离动态计算滚动速度，设置最小速度为3，最大速度为8
                    int scrollSpeed = 0;
                    if (dragStartPoint != null && currentPoint != null) {
                        if (scrollDirection == -1) {
                            // 向上滚动，计算鼠标距离起始点的距离
                            int distance = dragStartPoint.y - 50 - currentPoint.y;
                            // 设置最小速度为3，最大速度为8
                            scrollSpeed = Math.min(8, Math.max(3, distance / 5));
                        } else if (scrollDirection == 1) {
                            // 向下滚动，计算鼠标距离起始点的距离
                            int distance = currentPoint.y - (dragStartPoint.y + 50);
                            // 设置最小速度为3，最大速度为8
                            scrollSpeed = Math.min(8, Math.max(3, distance / 5));
                        }
                    }

                    if (scrollDirection == -1 && scrollSpeed > 0) {
                        // 向上滚动（减小viewPosition.y值，显示上方内容）
                        viewPosition.y = Math.max(0, viewPosition.y - scrollSpeed);
                    } else if (scrollDirection == 1 && scrollSpeed > 0) {
                        // 向下滚动（增大viewPosition.y值，显示下方内容）
                        viewPosition.y = Math.min(maxScroll, viewPosition.y + scrollSpeed);
                    }

                    viewport.setViewPosition(viewPosition);
                });

                autoScrollTimer.start();
            }

            /**
             * 停止自动滚动定时器
             */
            private void stopAutoScrollTimer() {
                if (autoScrollTimer != null) {
                    autoScrollTimer.stop();
                    autoScrollTimer = null;
                }
            }
        }));
    }

    /**
     * 在拖拽操作后更新列表模型
     *
     * @param fromIndex 原始索引
     * @param toIndex   目标索引
     */
    private void updateListModelAfterDrag(int fromIndex, int toIndex) {
        // 保存当前的滚动位置
        JScrollPane scrollPane = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, selectedFilesList);
        final Point[] savedViewPosition = {null};
        if (scrollPane != null) {
            savedViewPosition[0] = scrollPane.getViewport().getViewPosition();
        }

        // 直接移动列表模型中的元素，而不是清空后重新添加
        String movedItem = selectedFilesListModel.remove(fromIndex);
        selectedFilesListModel.add(toIndex, movedItem);

        // 只更新移动的项目显示（因为BPM信息可能需要更新）
        File movedFile = sharedSelectedFiles.get(toIndex);
        String fileName = movedFile.getName();

        // 检查是否有BPM数据
        String bpmInfo = "";
        if (songData != null && songData.containsKey(movedFile)) {
            Song song = songData.get(movedFile);
            if (song != null && song.getBpm() > 0) {
                bpmInfo = String.format("%.2f BPM", song.getBpm());
            }
        }

        // 格式化显示：使用HTML表格确保文件名左对齐，BPM右对齐
        String formattedName;
        if (!bpmInfo.isEmpty()) {
            formattedName = String.format("<html><table width='300'><tr>" +
                            "<td width='220' align='left'><nobr>%s</nobr></td>" +
                            "<td width='80' align='right'><nobr>%s</nobr></td>" +
                            "</tr></table></html>",
                    fileName.length() > 30 ? fileName.substring(0, 27) + "..." : fileName,
                    bpmInfo);
        } else {
            // 即使没有BPM信息，也使用相同的HTML表格布局保持对齐
            formattedName = String.format("<html><table width='300'><tr>" +
                            "<td width='220' align='left'><nobr>%s</nobr></td>" +
                            "<td width='80' align='right'></td>" +
                            "</tr></table></html>",
                    fileName.length() > 30 ? fileName.substring(0, 27) + "..." : fileName);
        }

        // 更新移动项目的显示
        selectedFilesListModel.set(toIndex, formattedName);

        // 如果原始位置仍然在列表范围内，也需要更新原始位置的显示
        if (fromIndex < selectedFilesListModel.size()) {
            File fromFile = sharedSelectedFiles.get(fromIndex);
            String fromFileName = fromFile.getName();

            // 检查是否有BPM数据
            String fromBpmInfo = "";
            if (songData != null && songData.containsKey(fromFile)) {
                Song song = songData.get(fromFile);
                if (song != null && song.getBpm() > 0) {
                    fromBpmInfo = String.format("%.2f BPM", song.getBpm());
                }
            }

            // 格式化显示：使用HTML表格确保文件名左对齐，BPM右对齐
            String fromFormattedName;
            if (!fromBpmInfo.isEmpty()) {
                fromFormattedName = String.format("<html><table width='300'><tr>" +
                                "<td width='220' align='left'><nobr>%s</nobr></td>" +
                                "<td width='80' align='right'><nobr>%s</nobr></td>" +
                                "</tr></table></html>",
                        fromFileName.length() > 30 ? fromFileName.substring(0, 27) + "..." : fromFileName,
                        fromBpmInfo);
            } else {
                // 即使没有BPM信息，也使用相同的HTML表格布局保持对齐
                fromFormattedName = String.format("<html><table width='300'><tr>" +
                                "<td width='220' align='left'><nobr>%s</nobr></td>" +
                                "<td width='80' align='right'></td>" +
                                "</tr></table></html>",
                        fromFileName.length() > 30 ? fromFileName.substring(0, 27) + "..." : fromFileName);
            }

            // 更新原始位置的显示
            selectedFilesListModel.set(fromIndex, fromFormattedName);
        }

        // 恢复滚动位置
        if (scrollPane != null && savedViewPosition[0] != null) {
            SwingUtilities.invokeLater(() -> {
                scrollPane.getViewport().setViewPosition(savedViewPosition[0]);
            });
        }
    }

    /**
     * 智能选取功能 - 随机选择歌曲直到达到指定时长
     */
    private void smartSelect() {
        try {
            double targetDuration = Double.parseDouble(durationField.getText());
            if (targetDuration <= 0 || targetDuration > 360) {
                // 获取主窗口作为父组件，使对话框在屏幕中央显示
                Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
                JOptionPane.showMessageDialog(parentFrame, languageManager.getString("dialog.update.check.failed"), languageManager.getString("panel.common.error.title"), JOptionPane.ERROR_MESSAGE);
                return;
            }

            // 显示进度对话框
            JDialog progressDialog = showProgressDialog(languageManager.getPanelText("selected.files.smart.select"));

            // 在新线程中执行智能选取
            new Thread(() -> {
                try {
                    // 获取MainUI实例中的文件列表（这里需要从FileListPanel获取）
                    List<File> allFiles = allListFiles;

                    // 清空当前选择
                    sharedSelectedFiles.clear();

                    // 通知选择变化
                    notifySelectionChanged();

                    // 创建水桶算法实例
                    SongBucket bucket = new SongBucket(targetDuration);

                    // 随机打乱文件列表
                    List<File> shuffledFiles = new ArrayList<>(allFiles);
                    Collections.shuffle(shuffledFiles);

                    // 处理歌曲直到桶满
                    boolean isFull = bucket.processSongs(shuffledFiles);

                    // 如果第一次没有装满，继续处理更多批次
                    int batchSize = 500;
                    int startIndex = batchSize;
                    int loopCount = 1;
                    final int MAX_LOOPS = 5;

                    while (!isFull && startIndex < shuffledFiles.size() && loopCount < MAX_LOOPS) {
                        List<File> nextBatch = shuffledFiles.subList(startIndex,
                                Math.min(startIndex + batchSize, shuffledFiles.size()));
                        isFull = bucket.processSongs(nextBatch);
                        startIndex += batchSize;
                        loopCount++;
                    }

                    // 获取选中的歌曲
                    List<File> selectedList = bucket.getSourceList();
                    sharedSelectedFiles.addAll(selectedList);

                    // 更新UI
                    SwingUtilities.invokeLater(() -> {
                        progressDialog.dispose();
                        updateSelectedFiles();
                        notifySelectionChanged();
                        // 获取主窗口作为父组件，使对话框在屏幕中央显示
                        Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
                        JOptionPane.showMessageDialog(parentFrame,
                                languageManager.getPanelText("selected.files.count", sharedSelectedFiles.size()), 
                                languageManager.getString("panel.common.info.title"),
                                JOptionPane.INFORMATION_MESSAGE);
                    });

                } catch (Exception e) {
                    SwingUtilities.invokeLater(() -> {
                        progressDialog.dispose();
                        // 获取主窗口作为父组件，使对话框在屏幕中央显示
                        Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
                        JOptionPane.showMessageDialog(parentFrame,
                                languageManager.getPanelText("panel.playback.restore.error", e.getMessage()), 
                                languageManager.getString("panel.common.error.title"),
                                JOptionPane.ERROR_MESSAGE);
                        e.printStackTrace();
                    });
                }
            }).start();

        } catch (NumberFormatException e) {
            // 获取主窗口作为父组件，使对话框在屏幕中央显示
            Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
            JOptionPane.showMessageDialog(parentFrame, languageManager.getString("dialog.donation.qr.error"), languageManager.getString("panel.common.error.title"), JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * 智能追加功能 - 在当前选择基础上追加歌曲直到达到指定时长
     */
    private void smartAppend() {
        try {
            double targetDuration = Double.parseDouble(durationField.getText());
            if (targetDuration <= 0 || targetDuration > 360) {
                // 获取主窗口作为父组件，使对话框在屏幕中央显示
                Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
                JOptionPane.showMessageDialog(parentFrame, languageManager.getString("dialog.update.check.failed"), languageManager.getString("panel.common.error.title"), JOptionPane.ERROR_MESSAGE);
                return;
            }

            // 显示进度对话框
            JDialog progressDialog = showProgressDialog(languageManager.getPanelText("selected.files.smart.append"));

            // 记录追加前的数量
            int beforeCount = sharedSelectedFiles.size();

            // 在新线程中执行智能追加
            new Thread(() -> {
                try {
                    // 获取所有可用文件
                    List<File> allFiles = allListFiles;

                    // 创建处理批次（当前已选 + 可用文件）
                    List<File> processingBatch = new ArrayList<>(sharedSelectedFiles);

                    // 添加未选中的文件
                    List<File> unselectedFiles = new ArrayList<>();
                    for (File file : allFiles) {
                        if (!sharedSelectedFiles.contains(file)) {
                            unselectedFiles.add(file);
                        }
                    }

                    // 对未选中的文件进行随机化处理
                    Collections.shuffle(unselectedFiles);
                    processingBatch.addAll(unselectedFiles);

                    // 去重
                    Set<File> uniqueSet = new LinkedHashSet<>(processingBatch);
                    processingBatch = new ArrayList<>(uniqueSet);

                    // 创建水桶算法实例
                    SongBucket bucket = new SongBucket(targetDuration);

                    // 处理歌曲
                    boolean isFull = bucket.processSongs(processingBatch);

                    // 如果第一次没有装满，继续处理更多批次
                    int batchSize = 1000;
                    int startIndex = processingBatch.size();
                    int loopCount = 1;
                    final int MAX_LOOPS = 5;

                    while (!isFull && startIndex < allFiles.size() && loopCount < MAX_LOOPS) {
                        List<File> nextBatch = allFiles.subList(startIndex,
                                Math.min(startIndex + batchSize, allFiles.size()));
                        // 对下一批次的文件进行随机化处理
                        Collections.shuffle(nextBatch);
                        isFull = bucket.processSongs(nextBatch);
                        startIndex += batchSize;
                        loopCount++;
                    }

                    // 获取选中的歌曲
                    List<File> selectedList = bucket.getSourceList();
                    sharedSelectedFiles.clear();
                    sharedSelectedFiles.addAll(selectedList);

                    // 计算实际追加的数量
                    int afterCount = sharedSelectedFiles.size();
                    int actualAppendedCount = afterCount - beforeCount;

                    // 更新UI
                    SwingUtilities.invokeLater(() -> {
                        progressDialog.dispose();
                        updateSelectedFiles();
                        notifySelectionChanged();
                        // 获取主窗口作为父组件，使对话框在屏幕中央显示
                        Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
                        JOptionPane.showMessageDialog(parentFrame,
                                languageManager.getPanelText("selected.files.count", actualAppendedCount), 
                                languageManager.getString("panel.common.info.title"),
                                JOptionPane.INFORMATION_MESSAGE);
                    });

                } catch (Exception e) {
                    SwingUtilities.invokeLater(() -> {
                        progressDialog.dispose();
                        // 获取主窗口作为父组件，使对话框在屏幕中央显示
                        Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
                        JOptionPane.showMessageDialog(parentFrame,
                                languageManager.getPanelText("panel.playback.restore.error", e.getMessage()), 
                                languageManager.getString("panel.common.error.title"),
                                JOptionPane.ERROR_MESSAGE);
                        e.printStackTrace();
                    });
                }
            }).start();

        } catch (NumberFormatException e) {
            // 获取主窗口作为父组件，使对话框在屏幕中央显示
            Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
            JOptionPane.showMessageDialog(parentFrame, languageManager.getString("dialog.donation.qr.error"), languageManager.getString("panel.common.error.title"), JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * 显示进度对话框
     */
    private JDialog showProgressDialog(String title) {
        // 获取主窗口作为父组件，使对话框在屏幕中央显示
        Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
        JDialog progressDialog = new JDialog(parentFrame, title, false);
        progressDialog.setLayout(new BorderLayout());
        progressDialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);

        JPanel progressPanel = new JPanel();
        progressPanel.setLayout(new BoxLayout(progressPanel, BoxLayout.Y_AXIS));
        progressPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));

        JLabel progressLabel = new JLabel(languageManager.getPanelText("playback.restore.progress"));
        progressLabel.setAlignmentX(Component.CENTER_ALIGNMENT);

        JProgressBar progressBar = new JProgressBar();
        progressBar.setIndeterminate(true);
        progressBar.setAlignmentX(Component.CENTER_ALIGNMENT);

        progressPanel.add(progressLabel);
        progressPanel.add(Box.createVerticalStrut(10));
        progressPanel.add(progressBar);

        progressDialog.add(progressPanel);
        progressDialog.pack();
        // 设置对话框在主窗口中心显示
        progressDialog.setLocationRelativeTo(parentFrame);
        progressDialog.setVisible(true);

        return progressDialog;
    }




    /**
     * 更新已选择文件列表
     *
     */
    public void updateSelectedFiles() {
        selectedFilesListModel.clear();
        for (File file : sharedSelectedFiles) {
            String fileName = file.getName();

            // 检查是否有BPM数据
            String bpmInfo = "";
            if (songData != null && songData.containsKey(file)) {
                Song song = songData.get(file);
                if (song != null && song.getBpm() > 0) {
                    bpmInfo = String.format("%.2f BPM", song.getBpm());
                }
            }

            // 格式化显示：使用HTML表格确保文件名左对齐，BPM右对齐
            String formattedName;
            if (!bpmInfo.isEmpty()) {
                formattedName = String.format("<html><table width='300'><tr>" +
                                "<td width='220' align='left'><nobr>%s</nobr></td>" +
                                "<td width='80' align='right'><nobr>%s</nobr></td>" +
                                "</tr></table></html>",
                        fileName.length() > 30 ? fileName.substring(0, 27) + "..." : fileName,
                        bpmInfo);
            } else {
                // 即使没有BPM信息，也使用相同的HTML表格布局保持对齐
                formattedName = String.format("<html><table width='300'><tr>" +
                                "<td width='220' align='left'><nobr>%s</nobr></td>" +
                                "<td width='80' align='right'></td>" +
                                "</tr></table></html>",
                        fileName.length() > 30 ? fileName.substring(0, 27) + "..." : fileName);
            }

            selectedFilesListModel.addElement(formattedName);
        }
        selectedCountLabel.setText(languageManager.getPanelText("selected.files.count", sharedSelectedFiles.size()));

        // 如果有文件，滚动到顶部
        if (selectedFilesListModel.getSize() > 0) {
            selectedFilesList.ensureIndexIsVisible(0);
        }
    }

    /**
     * 清空已选择文件列表
     */
    public void clearSelectedFiles() {
        sharedSelectedFiles.clear();
        selectedFilesListModel.clear();
        selectedCountLabel.setText(languageManager.getPanelText("selected.files.count", 0));
        notifySelectionChanged();
    }

    /**
     * 选择列表发生变化.
     */

    public void onSelectionChanged() {
        // 不需要参数，直接使用共享的selectedFiles集合
        updateSelectedFiles();
    }

    /**
     * 通知选择变化
     */
    private void notifySelectionChanged() {
        appStateManager.updateSelectedFiles();
    }





    /**
     * 更新单个文件的BPM显示
     */
    public void updateFileBPMDisplay(File file) {
        if (sharedSelectedFiles == null || !sharedSelectedFiles.contains(file)) {
            return;
        }

        // 找到文件在列表中的位置
        int index = sharedSelectedFiles.indexOf(file);
        if (index >= 0 && index < selectedFilesListModel.size()) {
            // 重新格式化该项目的显示文本
            String fileName = file.getName();
            String bpmInfo = "";

            if (songData != null && songData.containsKey(file)) {
                Song song = songData.get(file);
                if (song != null && song.getBpm() > 0) {
                    bpmInfo = String.format("%.2f BPM", song.getBpm());
                }
            }

            // 使用HTML表格确保BPM在最右侧对齐显示
            String formattedName;
            if (!bpmInfo.isEmpty()) {
                // HTML表格布局：文件名左对齐，BPM右对齐
                formattedName = String.format("<html><table width='300'><tr>" +
                                "<td width='220' align='left'><nobr>%s</nobr></td>" +
                                "<td width='80' align='right'><nobr>%s</nobr></td>" +
                                "</tr></table></html>",
                        fileName.length() > 30 ? fileName.substring(0, 27) + "..." : fileName,
                        bpmInfo);
            } else {
                // 即使没有BPM信息，也使用相同的HTML表格布局保持对齐
                formattedName = String.format("<html><table width='300'><tr>" +
                                "<td width='220' align='left'><nobr>%s</nobr></td>" +
                                "<td width='80' align='right'></td>" +
                                "</tr></table></html>",
                        fileName.length() > 30 ? fileName.substring(0, 27) + "..." : fileName);
            }

            // 更新列表中的特定项目
            selectedFilesListModel.set(index, formattedName);
        }
    }

    /**
     * 初始化收藏弹出菜单
     */
    private void initFavoritesPopup() {
        favoritesPopup = new JPopupMenu();
        favoritesPopup.setLayout(new BorderLayout());

        // 初始化收藏列表模型和列表
        favoritesListModel = new DefaultListModel<>();
        favoritesList = new JList<>(favoritesListModel);
        favoritesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        // 设置自定义渲染器，添加删除按钮
        favoritesList.setCellRenderer(new ListCellRenderer<String>() {
            @Override
            public Component getListCellRendererComponent(JList<? extends String> list, String value, int index,
                                                          boolean isSelected, boolean cellHasFocus) {
                // 创建主面板
                JPanel panel = new JPanel(new BorderLayout());
                panel.setOpaque(true);

                // 创建收藏名称标签
                JLabel nameLabel = new JLabel(value);
                nameLabel.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5));

                // 创建删除按钮
                JLabel deleteButton = new JLabel("×"); // 使用×符号作为删除按钮
                deleteButton.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5));
                deleteButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
                deleteButton.setToolTipText(languageManager.getString("panel.common.info.title"));

                // 设置选中状态的背景和前景色
                if (isSelected) {
                    panel.setBackground(list.getSelectionBackground());
                    nameLabel.setForeground(list.getSelectionForeground());
                    deleteButton.setForeground(list.getSelectionForeground());
                } else {
                    panel.setBackground(list.getBackground());
                    nameLabel.setForeground(list.getForeground());
                    deleteButton.setForeground(Color.RED);
                }

                // 将组件添加到面板
                panel.add(nameLabel, BorderLayout.CENTER);
                panel.add(deleteButton, BorderLayout.EAST);

                return panel;
            }
        });

        // 为收藏列表添加鼠标点击事件处理
        favoritesList.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                int index = favoritesList.locationToIndex(e.getPoint());
                if (index >= 0) {
                    // 获取点击位置对应的组件
                    Rectangle cellBounds = favoritesList.getCellBounds(index, index);
                    if (cellBounds != null) {
                        // 计算删除按钮的位置
                        int deleteButtonX = cellBounds.x + cellBounds.width - 30; // 假设删除按钮大约30像素宽

                        // 如果点击的是删除按钮区域
                        if (e.getX() > deleteButtonX) {
                            // 确认删除
                            String favoriteName = favoritesListModel.getElementAt(index);
                            Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
                            int result = JOptionPane.showConfirmDialog(parentFrame,
                                    languageManager.getPanelText("panel.production.confirm.stop"),
                                    languageManager.getPanelText("panel.production.stop.confirm"),
                                    JOptionPane.YES_NO_OPTION);

                            if (result == JOptionPane.YES_OPTION) {
                                // 删除收藏
                                favoritesManager.deleteFavorite(favoriteName);
                                // 更新列表
                                updateFavoritesList();

                                // 如果列表为空，关闭弹出菜单
                                if (favoritesListModel.getSize() == 0) {
                                    favoritesPopup.setVisible(false);
                                }
                            }
                        } else {
                            // 点击的是收藏名称区域，加载收藏
                            String selectedFavorite = favoritesListModel.getElementAt(index);
                            loadFavorite(selectedFavorite);
                            favoritesPopup.setVisible(false);  // 隐藏弹出菜单
                        }
                    }
                }
            }
        });

        // 添加滚动面板
        JScrollPane scrollPane = new JScrollPane(favoritesList);
        scrollPane.setPreferredSize(new Dimension(200, 150));
        favoritesPopup.add(scrollPane, BorderLayout.CENTER);
        favoritesPopup.setBorder(BorderFactory.createTitledBorder(languageManager.getPanelText("selected.files.favorites")));
    }

    /**
     * 设置收藏事件监听器
     */
    private void setupEventListeners() {
        // 收藏按钮事件监听器
        favoritesButton.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                showFavoritesPopup();
            }
        });

        // 加入收藏按钮事件监听器
        addFavoriteButton.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                addFavorite();
            }
        });
    }

    /**
     * 显示收藏弹出菜单
     */
    private void showFavoritesPopup() {
        // 更新收藏列表
        updateFavoritesList();

        if (favoritesListModel.getSize() == 0) {
            // 获取主窗口作为父组件，使对话框在屏幕中央显示
            Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
            JOptionPane.showMessageDialog(parentFrame, languageManager.getPanelText("selected.files.no.favorites"), languageManager.getString("panel.common.info.title"), JOptionPane.INFORMATION_MESSAGE);
            return;
        }

        // 在收藏按钮下方显示收藏弹出菜单
        favoritesPopup.show(favoritesButton,
                favoritesButton.getWidth() / 2 - favoritesPopup.getPreferredSize().width / 2,
                -favoritesPopup.getPreferredSize().height);
    }

    /**
     * 更新收藏列表
     */
    private void updateFavoritesList() {
        favoritesListModel.clear();
        List<String> favoriteNames = favoritesManager.getAllFavoriteNames();
        for (String name : favoriteNames) {
            favoritesListModel.addElement(name);
        }
    }

    /**
     * 加载选中的收藏
     */
    private void loadFavorite(String favoriteName) {
        List<File> favoriteFiles = new ArrayList<>(favoritesManager.loadFavorite(favoriteName));
        if (!favoriteFiles.isEmpty()) {
            // 替换当前已选择列表
            sharedSelectedFiles.clear();
            sharedSelectedFiles.addAll(favoriteFiles);

            // 更新UI
            updateSelectedFiles();
            notifySelectionChanged();

            // 根据用户需求，不再显示加载成功的提示信息
            // Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
            // JOptionPane.showMessageDialog(parentFrame, 
            //     "已加载收藏 '" + favoriteName + "'，共 " + favoriteFiles.size() + " 首歌曲", 
            //     "提示", 
            //     JOptionPane.INFORMATION_MESSAGE);
        } else {
            // 获取主窗口作为父组件，使对话框在屏幕中央显示
            Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
            JOptionPane.showMessageDialog(parentFrame,
                    languageManager.getPanelText("selected.files.load.empty", favoriteName),
                    languageManager.getString("panel.common.warning.title"),
                    JOptionPane.WARNING_MESSAGE);
        }
    }

    /**
     * 添加当前选择到收藏
     */
    private void addFavorite() {
        if (sharedSelectedFiles.isEmpty()) {
            // 获取主窗口作为父组件，使对话框在屏幕中央显示
            Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
            JOptionPane.showMessageDialog(parentFrame, languageManager.getPanelText("selected.files.no.selected"), languageManager.getString("panel.common.info.title"), JOptionPane.WARNING_MESSAGE);
            return;
        }

        // 显示收藏列表弹出菜单
        showAddFavoritePopup();
    }

    /**
     * 显示添加收藏弹出菜单
     */
    private void showAddFavoritePopup() {
        // 创建弹出菜单
        JPopupMenu addFavoritePopup = new JPopupMenu();
        addFavoritePopup.setLayout(new BorderLayout());

        // 初始化收藏列表模型和列表
        DefaultListModel<String> addFavoriteListModel = new DefaultListModel<>();
        JList<String> addFavoriteList = new JList<>(addFavoriteListModel);
        addFavoriteList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        // 获取所有收藏名称
        List<String> favoriteNames = favoritesManager.getAllFavoriteNames();

        // 添加现有的收藏列表
        for (String name : favoriteNames) {
            addFavoriteListModel.addElement(name);
        }

        // 如果有收藏项，添加分隔线
        if (!favoriteNames.isEmpty()) {
            addFavoriteListModel.addElement("---"); // 分隔线
        }

        // 添加"新建收藏列表+"选项
        addFavoriteListModel.addElement(languageManager.getPanelText("selected.files.add.new.favorite"));

        // 设置自定义渲染器
        addFavoriteList.setCellRenderer(new ListCellRenderer<String>() {
            @Override
            public Component getListCellRendererComponent(JList<? extends String> list, String value, int index,
                                                          boolean isSelected, boolean cellHasFocus) {
                // 创建主面板
                JPanel panel = new JPanel(new BorderLayout());
                panel.setOpaque(true);

                // 特殊处理分隔线
                if ("---".equals(value)) {
                    JSeparator separator = new JSeparator(JSeparator.HORIZONTAL);
                    separator.setPreferredSize(new Dimension(200, 10));
                    // 设置分隔线的边距以改善外观
                    separator.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5));
                    return separator;
                }

                // 创建收藏名称标签
                JLabel nameLabel = new JLabel(value);
                nameLabel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));

                // 特殊处理"新建收藏列表+"选项，使其居中显示
                if (languageManager.getPanelText("selected.files.add.new.favorite").equals(value)) {
                    nameLabel.setHorizontalAlignment(SwingConstants.CENTER);
                    // 为"新建收藏列表+"添加特殊样式以区分
                    nameLabel.setFont(nameLabel.getFont().deriveFont(Font.BOLD));
                } else {
                    nameLabel.setHorizontalAlignment(SwingConstants.LEFT);
                }

                // 设置选中状态的背景和前景色
                if (isSelected) {
                    panel.setBackground(list.getSelectionBackground());
                    nameLabel.setForeground(list.getSelectionForeground());
                } else {
                    panel.setBackground(list.getBackground());
                    nameLabel.setForeground(list.getForeground());
                }

                // 将组件添加到面板
                panel.add(nameLabel, BorderLayout.CENTER);

                return panel;
            }
        });

        // 为收藏列表添加鼠标点击事件处理
        addFavoriteList.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                int index = addFavoriteList.locationToIndex(e.getPoint());
                if (index >= 0 && index < addFavoriteListModel.getSize()) {
                    String selectedName = addFavoriteListModel.getElementAt(index);

                    // 忽略分隔线的点击
                    if ("---".equals(selectedName)) {
                        return;
                    }

                    // 如果点击的是"新建收藏列表+"选项
                    if (languageManager.getPanelText("selected.files.add.new.favorite").equals(selectedName)) {
                        // 关闭弹出菜单
                        addFavoritePopup.setVisible(false);

                        // 调用原来的弹窗输入收藏名称
                        createNewFavorite();
                    } else {
                        // 关闭弹出菜单
                        addFavoritePopup.setVisible(false);

                        // 将当前已选择的文件追加并去重到该收藏列表中
                        appendToFavorite(selectedName);
                    }
                }
            }
        });

        // 添加滚动面板
        JScrollPane scrollPane = new JScrollPane(addFavoriteList);
        // 设置滚动条策略
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

        // 禁用滚动面板的边框以改善外观
        scrollPane.setBorder(BorderFactory.createEmptyBorder());

        // 计算精确的高度以避免不必要的滚动条
        int itemHeight = 25; // 每个项目的大概高度
        int separatorHeight = 10; // 分隔线的高度
        int titleBorderHeight = 30; // 标题边框的高度
        int calculatedHeight = favoriteNames.size() * itemHeight;

        // 如果有分隔线，加上分隔线的高度
        if (!favoriteNames.isEmpty()) {
            calculatedHeight += separatorHeight;
        }

        // 加上"新建收藏列表+"选项的高度
        calculatedHeight += itemHeight;

        // 加上标题边框的高度
        calculatedHeight += titleBorderHeight;

        // 为了避免出现不必要的滚动条，我们稍微增加高度
        calculatedHeight += 5;

        // 限制最大高度，避免菜单过高
        int maxHeight = 300;
        int finalHeight = Math.min(calculatedHeight, maxHeight);

        // 设置首选尺寸
        scrollPane.setPreferredSize(new Dimension(200, finalHeight));
        // 设置最小尺寸以确保合适的显示
        scrollPane.setMinimumSize(new Dimension(200, 100));

        // 隐藏滚动条轨道以改善外观
        scrollPane.getVerticalScrollBar().setPreferredSize(new Dimension(0, 0));
        scrollPane.getVerticalScrollBar().setOpaque(false);

        addFavoritePopup.add(scrollPane, BorderLayout.CENTER);
        addFavoritePopup.setBorder(BorderFactory.createTitledBorder(languageManager.getPanelText("selected.files.add.to.favorites")));

        // 调整弹出菜单的大小策略
        addFavoritePopup.setPopupSize(new Dimension(210, finalHeight + 10));

        // 在加入收藏按钮下方显示弹出菜单
        addFavoritePopup.show(addFavoriteButton,
                addFavoriteButton.getWidth() / 2 - addFavoritePopup.getPreferredSize().width / 2,
                addFavoriteButton.getHeight());
    }

    /**
     * 创建新的收藏列表
     */
    private void createNewFavorite() {
        // 获取主窗口作为父组件，使对话框在屏幕中央显示
        Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
        String favoriteName = JOptionPane.showInputDialog(parentFrame, languageManager.getPanelText("selected.files.new.favorite.prompt"), languageManager.getPanelText("selected.files.new.favorite.title"), JOptionPane.QUESTION_MESSAGE);

        if (favoriteName != null && !favoriteName.trim().isEmpty()) {
            favoriteName = favoriteName.trim();

            // 保存收藏，将List转换为Set
            favoritesManager.saveFavorite(favoriteName, new LinkedHashSet<>(sharedSelectedFiles));

            JOptionPane.showMessageDialog(parentFrame,
                    languageManager.getPanelText("selected.files.count", sharedSelectedFiles.size()),
                    languageManager.getString("panel.common.info.title"),
                    JOptionPane.INFORMATION_MESSAGE);
        }
    }

    /**
     * 当时长输入验证成功时调用
     *
     * @param duration 验证通过的时长值
     */
    private void onDurationValidated(double duration) {
        // 在这里实现你想要执行的逻辑
        System.out.println(languageManager.getPanelText("panel.production.video.default.title", duration));

        // 持久化保存时长值
        prefs.putInt("duration", (int) duration);

        // 更新AppStateManager中的计划生成时长
        if (appStateManager != null) {
            appStateManager.setPlannedDuration(duration);
        }
    }


    /**
     * 将当前已选择的文件追加并去重到指定的收藏列表中
     */
    private void appendToFavorite(String favoriteName) {
        // 加载现有的收藏文件
        Set<File> existingFavoriteFiles = favoritesManager.loadFavorite(favoriteName);

        // 创建新的文件集合，包含现有的收藏文件和当前选择的文件
        Set<File> newFavoriteFiles = new LinkedHashSet<>(existingFavoriteFiles);
        newFavoriteFiles.addAll(sharedSelectedFiles);

        // 保存更新后的收藏
        favoritesManager.saveFavorite(favoriteName, newFavoriteFiles);

        // 获取主窗口作为父组件，使对话框在屏幕中央显示
        Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(SelectedFilePanel.this);
        JOptionPane.showMessageDialog(parentFrame,
                languageManager.getPanelText("selected.files.append.success", sharedSelectedFiles.size(), favoriteName, newFavoriteFiles.size()),
                languageManager.getString("panel.common.info.title"),
                JOptionPane.INFORMATION_MESSAGE);
    }
}